using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio;
using System.Runtime.InteropServices;
using System.IO;
using System.ComponentModel;
using Microsoft.Build.BuildEngine;

namespace Ferpect.GameComponents.Design
{
    internal static class DesignerUtilities
    {
        public static IVsHierarchy GetHierarchyForProject(EnvDTE.Project project)
        {
            if (project == null) throw new ArgumentNullException("project");

            IVsSolution solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution;
            IVsHierarchy hierarchy = null;
            int hr = solution.GetProjectOfUniqueName(project.UniqueName, out hierarchy);
            if (ErrorHandler.Failed(hr))
            {
                hierarchy = null;
            }
            return hierarchy;
        }

        public static readonly Guid ContentProjectTypeGuid = new Guid("{96E2B04D-8817-42c6-938A-82C39BA4D311}");

        public static IList<IVsHierarchy> GetNestedContentProjects(IVsHierarchy hierarchy)
        {
            List<IVsHierarchy> nestedProjects = new List<IVsHierarchy>();

            uint itemid = VSConstants.VSITEMID_NIL;

            int hr = VSConstants.S_OK;
            object property = null;

            hr = hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, out property);
            if (ErrorHandler.Succeeded(hr))
            {
                do
                {
                    itemid = (uint)(int)property;
                    Guid projectType;
                    hr = hierarchy.GetGuidProperty(itemid, (int)__VSHPROPID.VSHPROPID_TypeGuid, out projectType);
                    if (ErrorHandler.Succeeded(hr) && (projectType == VSConstants.GUID_ItemType_SubProject))
                    {
                        Guid iid_IVsHierarchy = typeof(IVsHierarchy).GUID;
                        IntPtr pHierNested = IntPtr.Zero;
                        uint nestedItemid = VSConstants.VSITEMID_NIL;
                        hr = hierarchy.GetNestedHierarchy(itemid, ref iid_IVsHierarchy, out pHierNested, out nestedItemid);
                        if (ErrorHandler.Succeeded(hr))
                        {
                            try
                            {
                                IVsHierarchy nestedProject = (IVsHierarchy)Marshal.GetObjectForIUnknown(pHierNested);
                                nestedProjects.Add(nestedProject);
                            }
                            finally
                            {
                                Marshal.Release(pHierNested);
                            }
                        }
                    }
                } while (ErrorHandler.Succeeded(hierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_NextVisibleSibling, out property)));
            }
            return nestedProjects;
        }

        public static void GetSpriteFontAssetNames(IVsHierarchy nestedContentHierarchy, IList<string> assetNames)
        {
            if (nestedContentHierarchy == null) throw new ArgumentNullException("nestedContentHierarchy");
            if (assetNames == null) throw new ArgumentNullException("assetNames");

            BuildItemGroup itemGroup = GetEvaluatedItemGroup(nestedContentHierarchy, "Compile");
            foreach (BuildItem buildItem in itemGroup)
            {
                string processor = buildItem.GetEvaluatedMetadata("Processor");
                if ((processor == "FontDescriptionProcessor") || (processor == "FontTextureProcessor"))
                {
                    string assetName = buildItem.GetEvaluatedMetadata("Name");
                    if (String.IsNullOrEmpty(assetName))
                    {
                        assetName = Path.GetFileNameWithoutExtension(buildItem.Include) + @"%0";
                    }
                    assetNames.Add(Path.Combine(Path.GetDirectoryName(buildItem.Include), assetName));
                }
            }
        }

        public static void GetTexture2DAssetNames(IVsHierarchy nestedContentHierarchy, List<string> assetNames)
        {
            if (nestedContentHierarchy == null) throw new ArgumentNullException("nestedContentHierarchy");
            if (assetNames == null) throw new ArgumentNullException("assetNames");

            BuildItemGroup itemGroup = GetEvaluatedItemGroup(nestedContentHierarchy, "Compile");
            foreach (BuildItem buildItem in itemGroup)
            {
                string processor = buildItem.GetEvaluatedMetadata("Processor");
                if (processor == "TextureProcessor")
                {
                    string assetName = buildItem.GetEvaluatedMetadata("Name");
                    if (String.IsNullOrEmpty(assetName))
                    {
                        assetName = Path.GetFileNameWithoutExtension(buildItem.Include) + @"%0";
                    }
                    assetNames.Add(Path.Combine(Path.GetDirectoryName(buildItem.Include), assetName));
                }
            }
        }

        public static BuildItemGroup GetEvaluatedItemGroup(IVsHierarchy hierarchy, string itemName)
        {
            if (hierarchy == null) throw new ArgumentNullException("hierarchy");
            if (itemName == null) throw new ArgumentNullException("itemName");

            IVsProject vsProject = (IVsProject)hierarchy;
            string mkDocument;
            ErrorHandler.ThrowOnFailure(vsProject.GetMkDocument(VSConstants.VSITEMID_ROOT, out mkDocument));
            Project project = Engine.GlobalEngine.GetLoadedProject(mkDocument);
            return project.GetEvaluatedItemsByName(itemName);
        }
    }
}
